<template>
  <el-button type="danger" @click="deleteMenusAll">删除</el-button>
  <el-tree
      ref="MenuTree"
      style="max-width: 600px"
      :data="tdata"
      show-checkbox
      :expand-on-click-node="false"
      :props="defaultProps"
      :default-expanded-keys="expandedKeys"
      node-key="catId"
      :draggable="true"
      :allow-drop="allowDrop"
      @node-drop="handleDrop"
  >
    <template #default="{ node, data }">
      <div class="custom-tree-node">
        <span>{{ node.label }}</span>
        <div>
          <el-button type="primary" v-if="node.level <= 2" link @click="append(data)">
            添加
          </el-button>
          <el-button type="primary" link @click="editor(data)">
            修改
          </el-button>
          <el-button v-if="node.childNodes.length === 0"
                     style="margin-left: 4px" type="danger" link
                     @click="remove(node, data)"
          >删除
          </el-button>
        </div>
      </div>
    </template>
  </el-tree>

  <el-dialog v-model="dialogFormVisible" :title="title" width="500" :close-on-click-modal="false">
    <el-form :model="form">
      <el-form-item label="分类名称">
        <el-input v-model="form.name" autocomplete="off"/>
      </el-form-item>
      <el-form-item label="图标">
        <el-input v-model="form.icon" autocomplete="off"/>
      </el-form-item>
      <el-form-item label="计量单位">
        <el-input v-model="form.productUnit" autocomplete="off"/>
      </el-form-item>
      <el-form-item label="排序">
        <el-input type="number" v-model="form.sort" autocomplete="off"/>
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="dialogFormVisible = false">关闭</el-button>
        <el-button type="primary" @click="handleConfirm">
          确认
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>
<style lang="scss">
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}


</style>
<script setup lang="ts">
import { defineComponent, ref } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import type { TreeInstance } from 'element-plus'
import {
  deleteMenus,
  getCategoryMenus,
  addCategory,
  updateCategory,
  getCategory,
  updateListCategory
} from '@/api/product/category'

defineComponent({
  name: 'category'
})

interface UpdateData {
  catId: number
  sort?: number
  parentCid?: number
  catLevel?: number
}

const updates: UpdateData[] = []

const MenuTree = ref<TreeInstance>()
const defaultProps = { children: 'children', label: 'name' }
const title = ref('')
const tdata = ref<any>([])
const expandedKeys = ref<number[]>([])
const form = ref<any>({})
const dialogFormVisible = ref(false)
const fdata = ref({
  catLevel: NaN,
  catId: NaN
})

async function deleteMenusAll() {
  await ElMessageBox.confirm(`确认要删除所选吗？`, {
    confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning'
  })
  const nodes = MenuTree.value?.getCheckedNodes().map(c => c.catId) as number[]
  await deleteMenus(nodes)
  await getMenus()
  ElMessage.success('菜单删除成功')
}

function updateChildrenNode( node ) {
  node.childNodes.forEach(node2 => {
    updates.push({ catId: node2.data.catId, catLevel: node2.level })
    updateChildrenNode(node2)
  })
}

async function handleDrop( dragNode, dropNode, type ) {
  // 1. 当前节点最新的父节点Id
  let pcid
  let siblings
  if (type === 'before' || type === 'after') {
    pcid = dropNode.data.parentCid
    siblings = dropNode.parent.childNodes
  } else {
    pcid = dropNode.data.catId
    siblings = dropNode.childNodes
  }
  updates.length = 0
  // 2. 当前节点的最新顺序
  siblings.forEach(( node, index ) => {
    let catLevel
    if (node.data.catId === dragNode.data.catId) {
      // 3. 当前拖拽节点的最新层级
      // 当前节点的层级变化
      catLevel = dragNode.level
      // 修改他的子节点层级
      updateChildrenNode(node)
      // 如果遍历的是当前正在拖拽的节点
      updates.push({ catId: node.data.catId, sort: index, parentCid: pcid, catLevel })
    } else {
      updates.push({ catId: node.data.catId, sort: index })
    }
  })
  await updateListCategory(updates)
  maxLevel.value = 0
  ElMessage.success('菜单修改成功')
}

const maxLevel = ref(0)

function countNodeLevel( node ) {
  // 求出最大的深度
  if (node.childNodes != null && node.childNodes.length > 0) {
    node.childNodes.forEach(child => {
      if (child.level > maxLevel.value) {
        maxLevel.value = child.level
      }
      countNodeLevel(child)
    })
  }
}

function allowDrop( draggingNode, dropNode, type ) {
  // 1. 被拖动的当前节点以及所在的父节点总层数不能大于 3
  countNodeLevel(draggingNode)
  // 当前正在拖动的节点 + 父节点所在的深度不大于 3 即可
  const deep = Math.abs((maxLevel.value - draggingNode.level)) + 1
  if (type === 'inner') {
    return deep + dropNode.level <= 3
  }
  return deep + dropNode.parent.level <= 3
}

async function editor( data ) {
  form.value = await getCategory(data.catId)
  title.value = '修改菜单'
  dialogFormVisible.value = true
}

async function getMenus() {
  tdata.value = await getCategoryMenus()
}

function append( data ) {
  title.value = '添加菜单'
  form.value = {}
  fdata.value = data
  dialogFormVisible.value = true
}

async function handleConfirm() {
  if (form.value.catId) {
    await updateCategory(form.value)
    ElMessage.success('菜单修改成功')
    expandedKeys.value = [ form.value.parentCid ]
  } else {
    const data = {
      catLevel: fdata.value.catLevel + 1, parentCid: fdata.value.catId, sort: form.value.sort,
      name: form.value.name, icon: form.value.icon, productUnit: form.value.productUnit
    }
    await addCategory(data)
    ElMessage.success('菜单保存成功')
    expandedKeys.value = [ fdata.value.catId ]
  }
  await getMenus()
  dialogFormVisible.value = false
}

async function remove( node, data ) {
  await ElMessageBox.confirm(`确认要删除${data.name}吗？`, {
    confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning'
  })
  await deleteMenus([ data.catId ])
  await getMenus()
  expandedKeys.value = [ data.parentCid ]
  ElMessage.success('菜单删除成功')
}

getMenus()
</script>
